package model;


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;


/**
 * Simplest client possible
 * 
 * @author johanrask
 *
 */
public class Test {

	private String address;
	private Snmp snmp;


	public Test(String address) {
		super();
		this.address = address;
		try {
			start();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	public void stop() throws IOException {
		snmp.close();
	}

	private void start() throws IOException {
		TransportMapping transport = new DefaultUdpTransportMapping();
		snmp = new Snmp(transport);
		transport.listen();
	}

	public String getAsString(OID oid) throws IOException {
		ResponseEvent event = get(new OID[]{oid});
		return event.getResponse().get(0).getVariable().toString();
	}


	public void getAsString(OID oids,ResponseListener listener) {
		try {
			snmp.send(getPDU(new OID[]{oids}), getTarget(),null, listener);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}


	private PDU getPDU(OID oids[]) {
		PDU pdu = new PDU();
		for (OID oid : oids) {
			pdu.add(new VariableBinding(oid));
		}

		pdu.setType(PDU.GET);
		return pdu;
	}

	public ResponseEvent get(OID oids[]) throws IOException {
		PDU pdu = new PDU();
		for (OID oid : oids) {
			pdu.add(new VariableBinding(oid));
		}
		pdu.setType(PDU.GET);
		ResponseEvent event = snmp.send(pdu, getTarget(), null);
		if(event != null) {
			return event;
		}
		throw new RuntimeException("GET timed out");
	}


	private Target getTarget() {
		Address targetAddress = GenericAddress.parse(address);
		CommunityTarget target = new CommunityTarget();
		target.setCommunity(new OctetString("public"));
		target.setAddress(targetAddress);
		target.setRetries(2);
		target.setTimeout(1500);
		target.setVersion(SnmpConstants.version2c);
		return target;
	}

	public List<List<String>> getTableAsStrings(OID[] oids) {
		TableUtils tUtils = new TableUtils(snmp, new DefaultPDUFactory());

		@SuppressWarnings("unchecked") 
		List<TableEvent> events = tUtils.getTable(getTarget(), oids, null, null);

		List<List<String>> list = new ArrayList<List<String>>();
		for (TableEvent event : events) {
			if(event.isError()) {
				throw new RuntimeException(event.getErrorMessage());
			}
			List<String> strList = new ArrayList<String>();
			list.add(strList);
			for(VariableBinding vb: event.getColumns()) {
				if(vb != null)
				strList.add(vb.getVariable().toString());
			}
		}
		return list;
	}

	public static String extractSingleString(ResponseEvent event) {
		return event.getResponse().get(0).getVariable().toString();
	}

	public static void main(String[] args) {
		try {
//			Test client = new Test("udp:10.0.0.50/161");
			
			// TRASNPORTE/ENDERECO/PORTA OBS: NAO SEI PQ MAIS SO ACEITA UDP E NAO TCP.
			Test client = new Test("udp:192.168.0.1/161");

			//PARA UM OID RETORNA A STRING DE RESPOSTA
			String sysDescr = client.getAsString(new OID(".1.3.6.1.2.1.1.1.0"));
			System.out.println(sysDescr);
			
			//PARA UM ARRAY DE OIDs RETORNA LINHAS DE RESPOSTAS
			OID[] oids = {(new OID(".1.3.6.1.2.1.1.1.0")),(new OID("1.3.6.1.4.1.2681.1.2.102"))};
			List<List<String>> systTable = client.getTableAsStrings(oids);
			for (List<String> list : systTable) {
				System.out.println();
				for (String line : list) {
					System.out.print(line+" ");
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}
